/******************************************************************************
 *      Mestrado em Ciência da Computação - UFMS
 *		Redes de Computadores - Prof. Dr. Ronaldo Alves Ferreira
 *		Alunos: Geraldo Landre, Marcel Tolentino, Vinícius Bueno
 *****************************************************************************/
/* tcpreset.c - tcpreset */

#include "tcpfms.h"
#include "tcp.h"

/*------------------------------------------------------------------------
 *  tcpreset -  generate a reset in response to a bad packet
 *------------------------------------------------------------------------
 */

//verificar
int tcpreset(struct udp *pudpin)
{
    struct udp *pudpout;

    struct tcp *ptcpin = (struct tcp*)(pudpin->udp_data);
    struct tcp *ptcpout;
    int datalen;
    
    if(ptcpin->tcp_code & TCPF_RST)
        return OK;		// no RESETs on RESETs
    
    pudpout = (struct udp *)malloc(sizeof(struct udp) );
    if(pudpout == NULL)
        return SYSERR;

    pudpout->ip_src = pudpin->ip_dst;
    pudpout->ip_dst = pudpin->ip_src;

    ptcpout = (struct tcp*)(pudpout->udp_data);
    ptcpout->tcp_sport = ptcpin->tcp_dport;
    ptcpout->tcp_dport = ptcpin->tcp_sport;
    
    if(ptcpin->tcp_code & TCPF_ACK) 
    {
        ptcpout->tcp_seq = ptcpin->tcp_ack;
        ptcpout->tcp_code = TCPF_RST;
    } 
    else 
    {
        ptcpout->tcp_seq = 0;
        ptcpout->tcp_code = TCPF_RST|TCPF_ACK;
    }
    
    datalen = TCP_HLEN(ptcpin);
    
    if(ptcpin->tcp_code & TCPF_SYN)
        datalen++;
    if(ptcpin->tcp_code & TCPF_FIN)
        datalen++;
    
    ptcpout->tcp_ack = ptcpin->tcp_seq + datalen;
    ptcpout->tcp_offset = TCPHOFFSET;
    ptcpout->tcp_window = ptcpout->tcp_urgptr = 0;
    tcph2net(ptcpout);
    ptcpout->tcp_cksum = 0;
    ptcpout->tcp_cksum = tcpcksum(pudpout, TCPMHLEN);
    TcpOutSegs++;
    TcpOutRsts++;

    // return ipsend(pipin->ip_src, tcpout, TCPMHLEN, IPT_TCP,IPP_NORMAL, IP_TTL);
    return udpsend(pudpout->ip_dst, ptcpout->tcp_dport, &ptcpout, sizeof(ptcpout));
}
